home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World Komputer 2007 December
/
PCWKCD1207B.iso
/
Blogowanie poza sfera
/
Flock 1.0 beta
/
flock-1.0RC3.en-US.win32.exe
/
flock
/
components
/
flockPiczoService.js
< prev
next >
Wrap
Text File
|
2007-10-18
|
61KB
|
1,854 lines
// vim: ts=2 sw=2 expandtab cindent
//
// BEGIN FLOCK GPL
//
// Copyright Flock Inc. 2005-2007
// http://flock.com
//
// This file may be used under the terms of of the
// GNU General Public License Version 2 or later (the "GPL"),
// http://www.gnu.org/licenses/gpl.html
//
// Software distributed under the License is distributed on an "AS IS" basis,
// WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
// for the specific language governing rights and limitations under the
// License.
//
// END FLOCK GPL
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cr = Components.results;
const Cu = Components.utils;
const CLASS_ID = Components.ID("{8DAEC4A0-8623-11DB-B606-0800200C9A66}");
const CLASS_NAME = "piczo";
const CLASS_DESC = "Flock Piczo Service";
const CONTRACT_ID = "@flock.com/people/piczo;1";
const FLOCK_PHOTO_ALBUM_CONTRACTID = "@flock.com/photo-album;1";
const FLOCK_PHOTO_ACCOUNT_CONTRACTID = "@flock.com/photo-account;1";
const SERVICE_ENABLED_PREF = "flock.service.piczo.enabled";
const CATEGORY_COMPONENT_NAME = "Piczo JS Component"
const CATEGORY_ENTRY_NAME = "piczo"
var gCompTK;
function getCompTK() {
if (!gCompTK) {
gCompTK = Components.classes["@flock.com/singleton;1"]
.getService(Components.interfaces.flockISingleton)
.getSingleton("chrome://browser/content/flock/services/common/load-compTK.js")
.wrappedJSObject;
}
return gCompTK;
}
var gTimers = []; // For use with the scheduler
// String defaults... may be updated later through Web Detective
var gStrings = {
"domains": "piczo.com",
"sessioncookie": "JSESSIONID",
"mainpage": "http://www.piczo.com/",
"favicon": "http://www.piczo.com/favicon.ico",
"userlogin": "http://www.piczo.com/",
"userprofile": "http://%accountid%.piczo.com/",
"api-agent-string": "Flock",
"api-setup-URL": "http://api.piczo.com/api-1/setup?api-agent=%agent%",
"api-login-URL": "http://api.piczo.com/api-1/login",
"api-friends-URL": "http://api.piczo.com/api-1/friends",
};
var gAPI = null;
var gSVC = null;
function loadLibraryFromSpec(aSpec)
{
var loader = Components.classes["@mozilla.org/moz/jssubscript-loader;1"]
.getService(Components.interfaces.mozIJSSubScriptLoader);
loader.loadSubScript(aSpec);
}
loadLibraryFromSpec("chrome://flock/content/common/flocksafe.js");
loadLibraryFromSpec("chrome://browser/content/flock/photo/photoAPI.js");
// ==============================================
// ========== BEGIN piczoService class ==========
// ==============================================
var _logger = null;
function piczoService()
{
_logger = Cc['@flock.com/logger;1'].createInstance(Ci.flockILogger);
_logger.init("piczo");
_logger.info("CONSTRUCTOR");
this.obs = Components.classes["@mozilla.org/observer-service;1"]
.getService(Components.interfaces.nsIObserverService);
this.acUtils = Components.classes["@flock.com/account-utils;1"]
.getService(Components.interfaces.flockIAccountUtils);
this.url = gStrings["mainpage"];
this.mIsInitialized = false;
this._ctk = {
interfaces: [
"nsISupports",
"nsIClassInfo",
"nsISupportsCString",
"nsIObserver",
"flockIWebService",
"flockIManageableWebService",
"flockIPollingService",
"flockIAuthenticateNewAccount",
"flockIMediaWebService",
"flockIMediaUploadAccount",
"flockIPiczoService"
],
shortName: "piczo",
fullName: "Piczo",
description: CLASS_DESC,
domains: gStrings["domains"],
favicon: gStrings["favicon"],
CID: CLASS_ID,
contractID: CONTRACT_ID,
accountClass: piczoAccount,
};
}
// BEGIN flockIMediaWebService interface
function createEnum( array ) {
return {
QueryInterface: function (iid) {
if (iid.equals(Ci.nsISimpleEnumerator)) {
return this;
}
throw Cr.NS_ERROR_NO_INTERFACE;
},
hasMoreElements: function() {
return (array.length > 0);
},
getNext: function() {
return array.shift();
}
}
}
function piczoPhoto() {
}
piczoPhoto.prototype= {
id: "",
thumbnail: "",
webPageUrl: "",
midSizePhoto: "",
largeSizePhoto: "",
title: "",
username: "",
userid: "",
is_public: true,
is_video: false,
svcShortName: 'piczo',
buildTooltip: function( ) {
// do we have to use document from the window to ceate elements? -- ja
var wm = Cc["@mozilla.org/appshell/window-mediator;1"].
getService(Ci.nsIWindowMediator);
var win = wm.getMostRecentWindow('navigator:browser');
if (!win) {
return null;
}
var hbox = win.document.createElement('hbox');
var img = win.document.createElement('image');
img.setAttribute('src', this.icon );
hbox.appendChild(img);
var box = win.document.createElement('vbox');
box.setAttribute('style', 'max-width: 250px');
var title = win.document.createElement('label');
title.setAttribute('value', this.title );
title.setAttribute('crop', 'end');
box.appendChild(title);
var lbl = win.document.createElement('label');
lbl.setAttribute('value', this.username );
lbl.setAttribute('class', 'user');
box.appendChild(lbl);
hbox.appendChild(box)
var vbox = win.document.createElement('vbox');
var cbox = win.document.createElement('hbox');
var largeImg = win.document.createElement('image');
largeImg.setAttribute('src', this.midSizePhoto);
largeImg.setAttribute('style', 'margin-bottom: 2px;');
var spacer = win.document.createElement('spacer');
spacer.setAttribute('flex', '1');
cbox.appendChild(largeImg);
cbox.appendChild(spacer);
vbox.appendChild(cbox);
vbox.appendChild(hbox);
return vbox;
},
buildHTML: function( ) {
return '<a title="'+this.title+'" href="'+this.webPageUrl+'"><img src="'+this.midSizePhoto+'" border="0" /></a>';
},
buildLargeHTML: function( ) {
return '<a title="'+this.title+'" href="'+this.webPageUrl+'"><img src="'+this.largeSizePhoto+'" border="0" /></a>';
},
buildBBCode: function ( ) {
return '[url=' + this.webPageUrl + '][img]'+ this.largeSizePhoto +'[/img][/url]';
},
QueryInterface: function(iid) {
if (!iid.equals(Ci.nsISupports) && !iid.equals(Ci.flockIPhoto)) {
throw Cr.NS_ERROR_NO_INTERFACE;
}
return this;
}
};
piczoService.prototype.iconUrl = gStrings["favicon"];
piczoService.prototype.handleDragDrop =
function piczoService_handleDragDrop (aURL, aXLoc, aYLoc) {
return gAPI.handleDragDrop(aURL, aXLoc, aYLoc);
}
piczoService.prototype.supportsFeature =
function piczoService_supportsFeature(aFeature)
{
var supports = {};
supports.tags = false;
supports.title = false;
supports.notes = false;
supports.fileName = false;
supports.contacts = true;
supports.privacy = false;
supports.albumCreation = false;
return (supports[aFeature] == true);
}
piczoService.prototype.login =
function piczoService_login(aAccountURN, aListener) {
_logger.info("piczoService.login()");
}
piczoService.prototype.__defineGetter__('isLoggedIn', function () { return gAPI.isLoggedIn(); })
piczoService.prototype.getAuthPerson = function () {
try {
var session = gAPI.getAuthUser();
var person = {};
person.id = session.userGUID;
person.fullname = session.username;
person.username = session.username;
person.service = this;
return person;
}
catch(e) {
return null;
}
}
piczoService.prototype.findByUsername =
function piczoService_findByUsername(aListener, aUsername) {
// Needed to have observer call .search();
aListener.onError(null);
}
piczoService.prototype.serviceName = "Piczo";
piczoService.prototype.shortName = "piczo";
piczoService.prototype.search =
function piczoService_search(aListener, aQueryString, aCount, aPage)
{
// Piczo doesn't support paging
if(aPage > 1) return;
// XXX: TODO
_logger.debug("piczoService_search: " + aQueryString);
var aQuery = new queryHelper(aQueryString);
var myListener = {
onSuccess: function (enumResults, status) {
aListener.onSearchResult(enumResults);
},
onError: function (aFlockError) {
//_logger.info("piczoService_search ERROR: " + aFlockError.serviceErrorString + "\n");
aListener.onError(aFlockError);
}
}
var params = Components.classes["@mozilla.org/hash-property-bag;1"]
.createInstance(Components.interfaces.nsIWritablePropertyBag2);
params.setPropertyAsAString("subj_id", aQuery.search);
params.setPropertyAsAString("albumlabel", aQuery.albumlabel);
if (gAPI.isLoggedIn())
{
gAPI.getPhotos(myListener, params);
} else {
_logger.info("piczoService wasnt logged in....");
// We are not logged in, force user to log in now.
var aError = Cc['@flock.com/error;1'].createInstance(Ci.flockIError);
aError.errorCode = Ci.flockIError.PHOTOSERVICE_USER_NOT_LOGGED_IN;
aListener.onError(aError);
}
}
piczoService.prototype.cancelUpload =
function piczoService_cancelUpload() {
try {
_logger.info("Cancelling upload...");
gAPI.uploader.req.abort();
} catch (e) {
_logger.info("Error cancelling upload.");
}
}
piczoService.prototype.upload =
function piczoService_upload(aListener, aUpload, aFile) {
_logger.info("piczoService_upload");
var params = {};
/*params.title = aUpload.title;
params.description = aUpload.description;
params.is_family = aUpload.is_family;
params.is_friend = aUpload.is_friend;
params.is_public = aUpload.is_public;
params.async = "1";
params.tags = aUpload.tags;
*/
gAPI.upload(aListener, aFile, params, aUpload);
}
piczoService.prototype.getAlbums =
function piczoService_getAlbums(aListener, aUserID) {
_logger.info("[piczoAPI].getAlbum call...");
var myListener = {
onResult: function (enumResults, status) {
_logger.info("[piczoAPI].getAlbums onResult!");
aListener.onGetAlbumsResult(enumResults);
},
onError: function (flockError) {
_logger.info("[piczoAPI].getAlbums onError!" + flockError.errorString);
//aListener.onError("Unable to get albums: " + flockError.errorString);
}
}
// NOTE: the uid needs to be changed to the uid of aUsername for general user searches
gAPI.getAlbums(myListener, aUserID);
}
/**
* getAlbumsForUpload
* @see flockIMediaWebService#getAlbumsForUpload
*/
piczoService.prototype.getAlbumsForUpload =
function piczoService_getAlbumsForUpload(aListener, aUsername) {
// Needs specific implementation for uploading albums
_logger.info("[piczoAPI].getAlbumsForUpload call...");
var myListener = {
onResult: function (enumResults, status) {
_logger.info("[piczoAPI].getAlbumsForUpload onResult!");
aListener.onGetAlbumsResult(enumResults);
},
onError: function (flockError) {
_logger.info("[piczoAPI].getAlbumsForUpload onError!" + flockError.errorString);
}
}
// NOTE: the uid needs to be changed to the uid of aUsername for general user searches
gAPI.getAlbumsForUpload(myListener, aUsername);
}
piczoService.prototype.getAccountStatus =
function piczoService_getAccountStatus(aListener) {
var inst = this;
var listener = {
onSuccess: function (aXML) {
_logger.info("piczoService: getAccountStatus Success!");
var result = Cc["@mozilla.org/hash-property-bag;1"]
.createInstance(Ci.nsIWritablePropertyBag2);
//var username = aXML.getElementsByTagName('username')[0].firstChild.nodeValue;
//var bandwidth = aXML.getElementsByTagName('bandwidth')[0];
//var maxFileSize = aXML.getElementsByTagName('filesize')[0];
//var isPro = aXML.getElementsByTagName('user')[0].getAttribute('ispro');
result.setPropertyAsAString("maxSpace", "500000");
result.setPropertyAsAString("usedSpace", "0");
result.setPropertyAsAString("maxFileSize", "500000");
result.setPropertyAsAString("usageUnits", "bytes");
result.setPropertyAsBool("isPremium", false);
aListener.onSuccess(result, "");
},
onError: function (aError) {
aListener.onError(aError);
_logger.info("piczoService: getAccountStatus ERROR");
}
}
gAPI.getAccountStatus(listener);
}
piczoService.prototype.call =
function piczoService_call(aListener, aMethod, aDictionary, aAuth)
{
_logger.info("piczoService_call");
return this.doCall(aListener, aMethod, aDictionary, aAuth);
}
piczoService.prototype.createAlbum =
function piczoService_createAlbum(aListener, aPath)
{
// XXX: TODO
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
}
piczoService.prototype.supportsSearch =
function piczoService_supportsSearch(aQueryString ) {
_logger.debug("piczoService_supportsSearch: " + aQueryString);
return false;
}
// BEGIN flockIWebService interface
piczoService.prototype.addAccountById =
function piczoService_addAccountById(aAccountID, aIsTransient, aListener)
{
_logger.info("{flockIWebService}.addAccountById('" + aAccountID + "', " + aIsTransient + ")");
var accountURN = "urn:flock:piczo:account:"+aAccountID;
var c_acct = new this._coop.Account(
accountURN, {
name: aAccountID,
accountId: aAccountID,
serviceId: CONTRACT_ID,
service: this.c_svc,
favicon: gStrings["favicon"],
URL: gStrings["userprofile"].replace("%accountid%", aAccountID),
isTransient: aIsTransient,
isPollable: true,
}
);
this._coop.accounts_root.children.add(c_acct);
// Instanciate account component
var acct = this.getAccount(c_acct.id());
if (aListener) aListener.onSuccess(acct, "addAccount");
return acct;
}
// END flockIWebService interface
piczoService.prototype.authenticateNewAccount =
function flickrService_authenticateNewAccount(aListener)
{
_logger.info("{flockIAuthenticateNewAccount}.authenticateNewAccount(aListener)");
var wm = Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator);
var win = wm.getMostRecentWindow('navigator:browser');
win.openUILinkIn(this.url, "tab");
}
// BEGIN flockIMediaWebService interface
piczoService.prototype.decorateForMedia =
function piczoService_decorateForMedia(aDocument)
{
_logger.info("{flockIMediaWebService}.decorateForMedia()");
// XXX TODO FIXME: implement
}
// END flockIMediaWebService interface
// BEGIN flockIManageableWebService interface
piczoService.prototype.getAccountIDFromDocument =
function piczoService_getAccountIDFromDocument(aDocument)
{
_logger.info("{flockIManageableWebService}.getAccountIDFromDocument()");
aDocument.QueryInterface(Components.interfaces.nsIDOMHTMLDocument);
var acctID;
var results = Components.classes["@mozilla.org/hash-property-bag;1"]
.createInstance(Components.interfaces.nsIWritablePropertyBag2);
if (this.webDetective.detect("piczo", "accountinfo", aDocument, results)) {
// If this page has the user GUID on it, then we can do a Coop lookup
// for accounts with that GUID
acctID = this._getAccountIDFromGUID(results.getPropertyAsAString("piczo_guid"));
}
if (!acctID) {
// We haven't determined the account yet.
// Since some login landing pages don't have account info on them that we
// can detect, we can try seeing if there's a session cookie stored as a
// temp password entry. (This is a hack.)
var sessionValue = this.acUtils.getCookie("http://piczo.com",
gStrings["sessioncookie"]);
if (!sessionValue) {
sessionValue = this.acUtils.getCookie("http://www.piczo.com",
gStrings["sessioncookie"]);
}
var pw = this.acUtils.getTempPassword("piczo:session:"+sessionValue);
if (pw) {
_logger.debug("Sneaky! Got acctID from a temp password associated with session cookie!");
acctID = pw.user;
}
}
return acctID;
}
piczoService.prototype.getCredentialsFromForm =
function piczoService_getCredentialsFromForm(aForm)
{
// Convenience method for Web Detective calls
var inst = this;
var detectForm = function piczo_detectForm(aType, aResults) {
return inst.webDetective.detectForm("piczo", aType, aForm, aResults);
};
// Try to detect login, then signup, then changepassword, in that order
var formType = "login";
var results = getCompTK().newResults();
if (!detectForm(formType, results)) {
// No login detected, so check for signup
formType = "signup";
results = getCompTK().newResults();
if (!detectForm(formType, results)) {
// No signup detected, so try changepassword
formType = "changepassword";
results = getCompTK().newResults();
if (!detectForm(formType, results)) {
results = null;
}
}
}
if (results) {
// We were able to get results from at least one of the checks above
var pw = {
QueryInterface: function(aIID) {
if (!aIID.equals(Components.interfaces.nsISupports) &&
!aIID.equals(Components.interfaces.nsIPassword) &&
!aIID.equals(Components.interfaces.flockIPassword))
{
throw Components.interfaces.NS_ERROR_NO_INTERFACE;
}
return this;
},
user: results.getPropertyAsAString("username"),
password: results.getPropertyAsAString("password"),
host: null,
formType: formType
};
// Doing a bit of a hack here...
// Since the Piczo login landing page doesn't always reveal which
// account is logged in, we will need to look at the session cookie and
// see if its the same as what it was when the user last logged in. So
// at this point we're just storing the account username as a temp
// password entry associated with the session cookie token.
var sessionValue = this.acUtils.getCookie("http://piczo.com",
gStrings["sessioncookie"]);
if (!sessionValue) {
sessionValue = this.acUtils.getCookie("http://www.piczo.com",
gStrings["sessioncookie"]);
}
this.acUtils.clearTempPassword("piczo:session:" + sessionValue);
this.acUtils.setTempPassword("piczo:session:" + sessionValue, pw.user, "",
formType);
return pw;
}
return null;
}
piczoService.prototype._getAccountIDFromGUID =
function piczoService__getAccountIDFromGUID(aGUID)
{
_logger.info("_getAccountIDFromGUID('" + aGUID + "')");
var accts = this._coop.Account.find({serviceId: CONTRACT_ID, piczo_guid: aGUID});
return (accts.length) ? accts[0].accountId : null;
}
piczoService.prototype.updateAccountStatusFromDocument =
function piczoService_updateAccountStatusFromDocument(aDocument)
{
_logger.info("{flockIManageableWebService}.updateAccountStatusFromDocument()");
if (this.webDetective.detect("piczo", "loggedout", aDocument, null)) {
this.acUtils.markAllAccountsAsLoggedOut(CONTRACT_ID);
} else if (this.webDetective.detect("piczo", "loggedin", aDocument, null)) {
var results = Components.classes["@mozilla.org/hash-property-bag;1"]
.createInstance(Components.interfaces.nsIWritablePropertyBag2);
var accountID = null;
var profileURL = null;
if (this.webDetective.detect("piczo", "accountinfo", aDocument, results)) {
var guid = results.getPropertyAsAString("piczo_guid");
accountID = this._getAccountIDFromGUID(guid);
// The profileURL is not always returned, so we need to test for it within
// a try/catch -> getPropertyAsAString will throw if it does not find the
// given property.
try {
profileURL = results.getPropertyAsAString("profileURL");
} catch (ex) {
// Didn't find profileURL. Just carry on.
_logger.debug("updateAccountStatusFromDocument: no profileURL: " + ex);
}
} else {
// Since some login landing pages don't have account info on them that we
// can detect, we can try seeing if there's a session cookie stored as a
// temp password entry. (This is a hack.)
var sessionValue = this.acUtils.getCookie("http://piczo.com",
gStrings["sessioncookie"]);
if (!sessionValue) {
sessionValue = this.acUtils.getCookie("http://www.piczo.com",
gStrings["sessioncookie"]);
}
var pw = this.acUtils.getTempPassword("piczo:session:"+sessionValue);
if (pw) {
_logger.debug("Sneaky! Got acctID from a temp password associated with session cookie!");
accountID = pw.user;
}
}
if (accountID && accountID.length) {
var accountURN = this.acUtils.getAccountURNById(this.urn, accountID);
if (accountURN) {
var c_acct = this._coop.get(accountURN);
var results2 = getCompTK().newResults();
if (this.webDetective.detect("piczo", "avatar", aDocument, results2)) {
c_acct.avatar = results2.getPropertyAsAString("avatarURL");
}
if (!c_acct.isAuthenticated) {
var acct = this.getAccount(accountURN);
acct.activate(null);
// Assume the API login will succeed. The listener should handle any
// failures...
c_acct.isAuthenticated = true;
}
if (profileURL && profileURL.length) {
c_acct.URL = profileURL;
}
}
}
}
}
// END flockIManageableWebService interface
///////////////////////////////////////
// BEGIN flockIPollingService interface
///////////////////////////////////////
piczoService.prototype.refresh =
function piczoService_refresh(aURN, aPollingListener)
{
_logger.info("{flockIPollingService}.refresh('" + aURN + "')");
aPollingListener.onResult();
}
// END flockIPollingService interface
piczoService.prototype.init =
function piczoService_init()
{
var _logger = Cc['@flock.com/logger;1'].createInstance(Ci.flockILogger);
_logger.init("piczoservice");
_logger.info(".init()");
// Prevent re-entry
if (this.mIsInitialized) return;
this.prefService = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefBranch);
if (this.prefService.getPrefType(SERVICE_ENABLED_PREF) &&
!this.prefService.getBoolPref(SERVICE_ENABLED_PREF))
{
_logger.info("Pref " + SERVICE_ENABLED_PREF + " set to FALSE... not initializing.");
var catMgr = Cc["@mozilla.org/categorymanager;1"]
.getService(Ci.nsICategoryManager);
catMgr.deleteCategoryEntry( "wsm-startup", CATEGORY_COMPONENT_NAME, true );
catMgr.deleteCategoryEntry( "flockWebService", CATEGORY_ENTRY_NAME, true );
catMgr.deleteCategoryEntry("flockMediaProvider", CATEGORY_ENTRY_NAME, true);
return;
}
this.mIsInitialized = true;
// Initialize API
this.mAPI = new piczoAPI();
gAPI = this.mAPI;
gAPI.defAlbum = {};
// Init global service handle
gSVC = this;
// Initialize Coop, service and actions
this._coop = Components.classes["@flock.com/singleton;1"]
.getService(Components.interfaces.flockISingleton)
.getSingleton("chrome://flock/content/common/load-faves-coop.js")
.wrappedJSObject;
this.urn = "urn:piczo:service";
this.c_svc = new this._coop.Service(
this.urn, {
name: CLASS_NAME,
desc: CLASS_DESC,
serviceId: CONTRACT_ID,
contactLabel: "Friends"
}
);
// Load Web Detective and update strings
this.webDetective = this.acUtils.useWebDetective("piczo.xml");
for (var s in gStrings) {
gStrings[s] = this.webDetective.getString("piczo", s, gStrings[s]);
}
this.url = gStrings["mainpage"];
this.domains = gStrings["domains"];
this.c_svc.domains = gStrings["domains"];
this.icon = gStrings["favicon"];
this.c_svc.loginURL = gStrings["userlogin"];
// Update account auth states
if (this.webDetective.detectCookies("piczo", "loggedout", null)) {
this.acUtils.markAllAccountsAsLoggedOut(CONTRACT_ID);
} else {
var acctURN = this.acUtils.getFirstAuthenticatedAccountForService(CONTRACT_ID);
try {
if (acctURN) {
var acct = this.getAccount(acctURN);
acct.activate(null);
}
} catch(e) {
_logger.info(".init() ERROR: " + e);
}
}
}
// ========== END piczoService class ==========
// ============================================================================================================================
// ========== BEGIN piczoAPI class ============================================================================================
// ============================================================================================================================
function piczoAPI()
{
_logger.info("[piczoAPI] CONSTRUCTOR");
this.mAPIToken = null;
this.mAPITokenID = null;
this.mSession = {
token: null,
userGUID: null,
username: null,
password: null
};
this.mTS = 0;
this.cryptoHash = Components.classes["@mozilla.org/security/hash;1"]
.createInstance(Components.interfaces.nsICryptoHash);
}
piczoAPI.prototype.getAuthUser =
function() {
return this.mSession;
}
piczoAPI.prototype.QueryInterface = function(iid) {
if (!iid.equals(Ci.nsIClassInfo) &&
!iid.equals(Ci.nsISupports)) {
throw Cr.NS_ERROR_NO_INTERFACE;
}
return this;
}
piczoAPI.prototype.getTS =
function piczoAPI_getTS()
{
return (this.mTS++);
}
piczoAPI.prototype.call =
function piczoAPI_call(aMethod, aURL, aCustomHeaders, aPostVars, aListener, aSign)
{
aMethod = aMethod.toUpperCase();
_logger.debug("[piczoAPI].call('" + aMethod + "', '" + aURL + "')");
var hr = Components.classes['@mozilla.org/xmlextras/xmlhttprequest;1']
.createInstance(Components.interfaces.nsIXMLHttpRequest);
hr.QueryInterface(Components.interfaces.nsIJSXMLHttpRequest);
hr.open(aMethod, aURL, true);
if (aMethod == "POST") {
hr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded", false);
}
// Per Bug #9373, Piczo API chokes on '+' characters in post vars, so we
// need this function to explicitly encode them.
var customEscape = function piczoAPI_customEscape(aText) {
return escape(aText).replace("+", "%2B");
};
if (aSign) {
// Need to compose message string and generate signature
var url = aURL;
var params = [];
var qmIdx = url.indexOf("?");
if (qmIdx > -1) {
var qString = url.substring(qmIdx + 1);
url = url.substring(0, qmIdx);
var qArr = qString.split("&");
for (var i = 0; i < qArr.length; i++) {
var prm = qArr[i].split("=");
params.push([prm[0], prm[1]]);
}
}
if (aCustomHeaders) {
for (var h in aCustomHeaders) {
params.push([h, aCustomHeaders[h]]);
}
}
if (aPostVars) {
for (var p in aPostVars) {
params.push([p, aPostVars[p]]);
}
}
params.sort();
////////////////////////////////////////////////////////
// Piczo Digital Signature format:
// ds := base-64( md5( {api-token} + {access-token} ) )
////////////////////////////////////////////////////////
var apitoken = "";
var accesstoken = "";
for (var i = 0; i < params.length; i++) {
if(params[i][0] == "at") {
accesstoken = params[i][1];
} else if(params[i][0] == "api-token") {
apitoken = params[i][1];
}
}
var msg = apitoken + accesstoken;
var msgArr = [];
for (var i = 0; i < msg.length; i++) {
msgArr.push(msg.charCodeAt(i));
}
this.cryptoHash.init(Components.interfaces.nsICryptoHash.MD5);
this.cryptoHash.update(msgArr, msgArr.length);
var sig = this.cryptoHash.finish(true);
var dsValue = escape(sig);
dsValue = dsValue.replace(/\+/g,"%2B");
dsValue = dsValue.replace(/\//g,"%2F");
dsValue = dsValue.replace(/\@/g,"%40");
_logger.debug("message: " + msg + " sig: " + dsValue);
hr.setRequestHeader("ds", dsValue);
}
if (aCustomHeaders) {
for (var h in aCustomHeaders) {
var val = escape(aCustomHeaders[h]);
val = val.replace(/\+/g,"%2B");
val = val.replace(/\//g,"%2F");
val = val.replace(/\@/g,"%40");
hr.setRequestHeader(h, val);
}
}
hr.onreadystatechange = function (aEvent) {
_logger.debug("[piczoAPI].call(): hr.onreadystatechange(): " + hr.readyState);
if (aListener) {
if (hr.readyState == 4) {
try {
if (hr.status/100 == 2) {
try {
aListener.onSuccess(hr, aURL);
} catch (ex) {
_logger.info(ex);
aListener.onError(hr, aURL, null);
}
} else {
// HTTP error
var err = {
errorCode: hr.status,
errorString: "HTTP error."
};
aListener.onError(hr, aURL, err);
}
} catch (ex) {
_logger.info(ex);
var err = {
errorCode: Components.interfaces.flockIError.PHOTOSERVICE_UNAVAILABLE,
errorString: "Request did not complete."
};
aListener.onError(hr, aURL, err);
}
}
}
};
var postBody = "";
if (aPostVars) {
for (var v in aPostVars) {
if (postBody.length) { postBody += "&"; }
postBody += v + "=" + customEscape(aPostVars[v]);
}
}
if ((aMethod == "POST") && postBody && postBody.length) {
hr.send(postBody);
} else {
hr.send(null);
}
}
piczoAPI.prototype.getAPIToken =
function piczoAPI_getAPIToken(aListener)
{
_logger.debug("[piczoAPI].getAPIToken()");
var api = this;
var setupListener = {
onSuccess: function (aSubject, aTopic) {
_logger.debug("[piczoAPI].getAPIToken() setupListener.onSuccess()");
_logger.debug(aSubject.responseText);
var xmlDoc = aSubject.responseXML;
var replyEl = xmlDoc.getElementsByTagName("setup.reply").item(0);
var tokenEl = replyEl.getElementsByTagName("api-token").item(0);
var tokenIDEl = replyEl.getElementsByTagName("id").item(0);
api.mAPIToken = tokenEl.childNodes.item(0).nodeValue;
api.mAPITokenID = tokenIDEl.childNodes.item(0).nodeValue;
_logger.debug(" got API token ID:" + api.mAPITokenID);
_logger.debug(" got API token: "+api.mAPIToken);
if (aListener) { aListener.onSuccess(aSubject, aTopic); }
},
onError: function (aSubject, aTopic, aError) {
_logger.info("[piczoAPI].getAPIToken() setupListener.onError()");
if (aError) {
for (var p in aError) {
_logger.info("error[" + p + "] = " + aError[p]);
}
}
for (var p in aSubject) {
_logger.debug("response[" + p + "] = " + aSubject[p]);
}
if (aListener) { aListener.onError(aSubject, aTopic, aError); }
}
};
var url = gStrings["api-setup-URL"].replace("%agent%", gStrings["api-agent-string"]);
var postVars = {
"api-agent": gStrings["api-agent-string"]
};
this.call("post", url, null, postVars, setupListener);
}
piczoAPI.prototype.getPhotosCall =
function piczoService_authenticatedGetPhotosCall(aListener, aMethod, aDictionary)
{
var api = this;
api.pageID = null;
api.pageToFind = aDictionary.albumlabel;
_logger.debug("piczoService_authenticatedCall " + aMethod);
if (!this.isLoggedIn) {
_logger.debug("not logged in, so trying unauth call for " + aMethod);
return this.call(aListener, aMethod, aDictionary);
}
var pageToFind = aDictionary.albumlabel;
var callGetPhotos = function () {
var url = "http://api.piczo.com/api-1/lookup";
if (api.pageID) {
url += "/" + api.pageID;
}
url += "/images?reply=rss";
var headers = {
"api-token": this.gAPI.mAPIToken,
"at": this.gAPI.mSession.token
};
api.call("get", url, headers, null, aListener, true);
};
var pagesListener = {
onSuccess: function pagesListener_onSuccess(aSubject, aTopic) {
var xml = aSubject.responseXML;
_logger.debug("[piczoAPI].getPages returned: "
+ aSubject.responseText);
var items = xml.getElementsByTagName("item");
for (var i = 0; i < items.length; i++) {
var guid = items[i].getElementsByTagName("guid")[0]
.firstChild.nodeValue;
var pagelabel = items[i].getElementsByTagName("description")[0]
.firstChild.nodeValue;
if (api.pageToFind == pagelabel) {
api.pageID = guid;
}
}
callGetPhotos();
return;
},
onError: function pagesListener_onError(aSubject, aTopic, aFlockError) {
_logger.error("Error getting pages" + aFlockError.errorString);
if (api.handleStaleToken(aSubject)) {
// Resubmit the request with the new token
api.getPhotosCall(aListener, "piczo.photos.get", aDictionary);
} else {
aListener.onError(aFlockError);
}
}
};
// Get Page ID first
var callGetPages = function callGetPages_function() {
var url = "http://api.piczo.com/api-1/lookup/pages?reply=rss";
var headers = {
"api-token": this.gAPI.mAPIToken,
"at": this.gAPI.mSession.token
};
api.call("get", url, headers, null, pagesListener, true);
}
if (this.mAPIToken) {
_logger.info("piczoService Calling getphotos");
if (pageToFind != null) {
callGetPages();
} else {
callGetPhotos();
}
} else {
_logger.info("piczoService wasnt logged in....");
// We are not logged in, force user to log in now.
var aError = Cc['@flock.com/error;1'].createInstance(Ci.flockIError);
aError.errorCode = Ci.flockIError.PHOTOSERVICE_USER_NOT_LOGGED_IN;
aListener.onError(aError);
}
}
piczoAPI.prototype.getAccountStatus =
function piczoAPI_getAccountStatus(aListener) {
_logger.info("[piczoAPI].getAccountStatus");
}
/**
* getAlbums
* @see flockIMediaWebService#getAlbums
*/
piczoAPI.prototype.getAlbums =
function piczoAPI_getAlbums(aListener, aParams) {
_logger.info("[piczoAPI].getAlbums('" + aParams + "')");
var api = this;
var pagesListener = {
onSuccess: function pagesListener_onSuccess(aSubject, aTopic) {
var xml = aSubject.responseXML;
_logger.debug("[piczoAPI].getPages returned: "
+ aSubject.responseText);
var photoAlbums = [];
var items = xml.getElementsByTagName("item");
for (var i = 0; i < items.length; i++) {
var guid = items[i].getElementsByTagName("guid")[0]
.firstChild.nodeValue;
var pagelabel = items[i].getElementsByTagName("description")[0]
.firstChild.nodeValue;
var newAlbum = Cc[FLOCK_PHOTO_ALBUM_CONTRACTID]
.createInstance(Ci.flockIPhotoAlbum);
newAlbum.id = guid;
newAlbum.title = pagelabel;
if (!gAPI.defAlbum.id) {
gAPI.defAlbum = newAlbum;
}
photoAlbums.push(newAlbum);
}
var albumsEnum = {
hasMoreElements: function() {
return (photoAlbums.length > 0);
},
getNext: function() {
return photoAlbums.shift();
}
}
aListener.onResult(albumsEnum, null);
},
onError: function pagesListener_onError(aSubject, aTopic, aFlockError) {
_logger.error("Error getting pages" + aFlockError.errorString);
if (api.handleStaleToken(aSubject)) {
// Resubmit the request with the new token
api.getAlbums(aListener, "piczo.photos.get", aDictionary);
} else {
aListener.onError(aFlockError);
}
}
};
// Get Page ID first
var callGetPages = function callGetPages_function() {
var url = "http://api.piczo.com/api-1/lookup/pages?reply=rss";
var headers = {
"api-token": this.gAPI.mAPIToken,
"at": this.gAPI.mSession.token
};
api.call("get", url, headers, null, pagesListener, true);
}
if (this.mAPIToken) {
_logger.debug("piczoService Calling getInbox");
callGetPages();
} else {
_logger.debug("piczoService wasnt logged in....");
// We are not logged in, force user to log in now.
var aError = Cc['@flock.com/error;1'].createInstance(Ci.flockIError);
aError.errorCode = Ci.flockIError.PHOTOSERVICE_USER_NOT_LOGGED_IN;
aListener.onError(aError);
}
}
/**
* getAlbumsForUpload
* @see flockIMediaWebService#getAlbumsForUpload
*/
piczoAPI.prototype.getAlbumsForUpload =
function piczoAPI_getAlbumsForUpload(aListener, aParams) {
_logger.debug("[piczoAPI].getAlbumsForUpload('" + aParams + "')");
var api = this;
// Make inbox call
//
var listener = {
onSuccess: function(aSubject, aTopic) {
//try {
var xml = aSubject.responseXML;
_logger.debug("[piczoAPI].getInbox returned: " + aSubject.responseText);
var destinations = xml.getElementsByTagName("destination");
var photoAlbums = [];
_logger.debug("[piczoAPI].getInbox parsing data: " + destinations.length);
gAPI.defAlbum = {};
for (var i = 0; i < destinations.length; i++) {
var name = destinations[i].getElementsByTagName('name')[0].firstChild.nodeValue;
var uri = destinations[i].getElementsByTagName('action-uri')[0].firstChild.nodeValue;
_logger.debug("[piczoAPI].getInbox data: " + name + ", " + uri);
var newAlbum = Components.classes[FLOCK_PHOTO_ALBUM_CONTRACTID]
.createInstance(Ci.flockIPhotoAlbum);
newAlbum.id = uri;
newAlbum.title = name;
if(!gAPI.defAlbum.id) {
gAPI.defAlbum = newAlbum;
}
photoAlbums.push(newAlbum);
}
var enum_ = {
hasMoreElements: function() {
return (photoAlbums.length > 0);
},
getNext: function() {
return photoAlbums.shift();
}
}
_logger.debug("[piczoAPI].getInbox returning results...");
aListener.onResult(enum_, null);
},
onError: function(aSubject, aTopic, aFlockError) {
_logger.info('Error getting inbox' + aFlockError.errorString);
if (api.handleStaleToken(aSubject)) {
// Resubmit the request with the new token
api.getAlbumsForUpload(aListener, aParams);
} else {
aListener.onError(aFlockError);
}
}
};
var callGetInbox = function () {
var url = "http://api.piczo.com/api-1/inbox" + "/images";
var headers = {
"api-token": this.gAPI.mAPIToken,
"at": this.gAPI.mSession.token
};
api.call("get", url, headers, null, listener, true);
};
if (this.mAPIToken) {
_logger.info("piczoService Calling getInbox");
callGetInbox();
} else {
_logger.info("piczoService wasnt logged in....");
// We are not logged in, force user to log in now.
var aError = Cc['@flock.com/error;1'].createInstance(Ci.flockIError);
aError.errorCode = Ci.flockIError.PHOTOSERVICE_USER_NOT_LOGGED_IN;
aListener.onError(aError);
return;
}
}
// Handle the case where the session token goes stale
// If stale reset and return true, otherwise return false
piczoAPI.prototype.handleStaleToken =
function(aSubject) {
// When a session token goes stale the piczo api
// marks the response with an http error (401 - unauthorized)
// and includes error information with a new session token
_logger.debug("handleStaleToken()");
var api = this;
if (aSubject.status == 401) {
var xml = aSubject.responseXML;
_logger.debug(aSubject.responseText);
var errorEl = xml.getElementsByTagName("errors").item(0);
if (!errorEl || (errorEl.length == 0)) {
return false;
}
var invalidCrdntlEl = errorEl.getElementsByTagName("error.invalid-credential").item(0);
if (!invalidCrdntlEl || (invalidCrdntlEl.length == 0)) {
return false;
}
var arglinkEl = invalidCrdntlEl.getElementsByTagName("argument").item(0);
if (!arglinkEl || (arglinkEl.length == 0)) {
return false;
}
var problem = arglinkEl.getAttribute("problem");
if (!problem) {
return false;
}
_logger.debug("problem = " + problem);
if (problem == "expired-access") {
// Our access token went stale so grab the new one from the response
var sessiontokenEl = errorEl.getElementsByTagName("at").item(0);
var sessiontoken = sessiontokenEl.childNodes.item(0).nodeValue;
_logger.debug("new access token = " + sessiontoken);
api.mSession.token = sessiontoken;
return true;
}
}
return false;
}
piczoAPI.prototype.getPhotos =
function piczoAPI_getPhotos(aListener, aParams) {
_logger.debug("[piczoAPI].getPhotos('" + aParams + "')");
var api = this;
var listener = {
onSuccess: function(aSubject, aTopic) {
var photos = [];
_logger.debug("[piczoAPI].getPhotos returned: " + aSubject.responseText);
var xml = aSubject.responseXML;
var photoList = xml.getElementsByTagName("item");
for (var i = 0; i < photoList.length; i++) {
var photo = photoList[i];
var id = photo.getElementsByTagName('guid')[0].firstChild.nodeValue;
var link = photo.getElementsByTagName('link')[0].firstChild.nodeValue;
var description = photo.getElementsByTagName('description')[0].firstChild.nodeValue;
var thumbnail = photo.getElementsByTagName("thumbnail")
.item(0)
.getAttribute("url");
var newPhoto = new piczoPhoto();
newPhoto.webPageUrl = link;
newPhoto.thumbnail = link;
newPhoto.midSizePhoto = thumbnail;
newPhoto.largeSizePhoto = link;
newPhoto.title = description;
newPhoto.id = id;
newPhoto.is_public = true;
newPhoto.is_video = false;
photos.unshift(newPhoto);
}
aListener.onSuccess(createEnum(photos), 'success');
},
onError: function(aSubject, aTopic, aFlockError) {
if(aFlockError) {
_logger.info('Error getting photos' + aFlockError.errorString);
} else {
_logger.info("Error getting photos");
}
if (api.handleStaleToken(aSubject)) {
// Resubmit the request with the new token
api.getPhotos(aListener,aParams);
} else {
aListener.onError(aFlockError);
}
}
};
var params = {
subj_id: aParams.getPropertyAsAString("subj_id"),
albumlabel: aParams.getPropertyAsAString("albumlabel")
};
_logger.info("calling getphotoscall");
api.getPhotosCall(listener, 'piczo.photos.get', params);
}
piczoAPI.prototype.login =
function piczoAPI_login(aUsername, aPassword, aListener)
{
_logger.debug("[piczoAPI].login('" + aUsername + "')");
var api = this;
if (aUsername) { this.mSession.username = aUsername; }
if (aPassword) { this.mSession.password = aPassword; }
var loginListener = {
onSuccess: function (aSubject, aTopic) {
_logger.info("[piczoAPI].login() loginListener.onSuccess()");
_logger.debug(aSubject.responseText);
var xmlDoc = aSubject.responseXML;
var replyEl = xmlDoc.getElementsByTagName("login.reply").item(0);
var userlinkEl = replyEl.getElementsByTagName("user.id").item(0);
api.mSession.userGUID = userlinkEl.getAttribute("guid");
_logger.debug(" got user GUID: "+api.mSession.userGUID);
var sessiontokenEl = replyEl.getElementsByTagName("at").item(0);
api.mSession.token = sessiontokenEl.childNodes.item(0).nodeValue;
_logger.debug(" got session token: "+api.mSession.token);
if (aListener) { aListener.onSuccess(aSubject, aTopic); }
},
onError: function (aSubject, aTopic, aError) {
_logger.info("[piczoAPI].login() loginListener.onError()");
if (aListener) { aListener.onError(aSubject, aTopic, aError); }
}
};
var callLogin = function () {
var url = gStrings["api-login-URL"];
var headers = {
"ts": api.getTS()
};
var postVars = {
"user-name": api.mSession.username,
"user-password": api.mSession.password,
"id": api.mAPITokenID,
"api-token": api.mAPIToken
};
api.call("post", url, headers, postVars, loginListener);
};
if (this.mAPIToken) {
callLogin();
} else {
// Need to get an API token before we can log in
var tokenListener = {
onSuccess: function (aSubject, aTopic) {
callLogin();
},
onError: function (aSubject, aTopic, aError) {
if (aListener) { aListener.onError(aSubject, aTopic, aError); }
}
};
this.getAPIToken(tokenListener);
}
}
piczoAPI.prototype.logout =
function piczoAPI_logout()
{
_logger.info("[piczoAPI].logout()");
this.mSession = [];
var api = this;
var logoutListener = {
onSuccess: function (aSubject, aTopic) {
_logger.info("[piczoAPI].logout() logoutListener.onSuccess()");
_logger.debug(aSubject.responseText);
var xmlDoc = aSubject.responseXML;
var replyEl = xmlDoc.getElementsByTagName("logout.reply").item(0);
},
onError: function (aSubject, aTopic, aError) {
_logger.info("[piczoAPI].logout() logoutListener.onError()");
}
};
var callLogout = function () {
var url = gStrings["api-logout-URL"];
var headers = {
"ts": api.getTS()
};
var postVars = {
"user-name": api.mSession.username,
"user-password": api.mSession.password,
"id": api.mAPITokenID,
"api-token": api.mAPIToken
};
api.call("post", url, headers, postVars, logoutListener);
};
if (this.mAPIToken) {
callLogout();
} else {
// Need to get an API token before we can log out
var tokenListener = {
onSuccess: function (aSubject, aTopic) {
callLogout();
},
onError: function (aSubject, aTopic, aError) {
if (aListener) { aListener.onError(aSubject, aTopic, aError); }
}
};
this.getAPIToken(tokenListener);
}
}
piczoAPI.prototype.upload =
function piczoAPI_upload(aListener, aPhoto, aParams, aUpload) {
_logger.info("piczoAPI_upload");
// XXX: TODO
var inst = this;
this.uploader = new PhotoUploader();
var myListener = {
onResult: function(aXML) {
_logger.debug("piczoAPI_upload: Got a result back from uploader: " + aXML.responseText);
aListener.onUploadComplete(aUpload);
},
onError: function(aErrorCode) {
_logger.info("piczoAPI_upload: " + aErrorCode);
aListener.onError(aErrorCode);
},
onProgress: function(aCurrentProgress) {
_logger.info("piczoAPI_upload: Progress");
aListener.onProgress(aCurrentProgress);
}
}
gAPI.convertBools(aParams);
gAPI.convertTags(aParams);
var dsvalue = this.getDSValue();
// Check for default album seleciton
if(!aUpload.album) {
// auto-select the first album
aUpload.album = gAPI.defAlbum.id;
}
this.uploader.setEndpoint(aUpload.album + "&ds=" + dsvalue);
this.uploader.upload(myListener, aPhoto, aParams);
}
piczoAPI.prototype.getDSValue =
function piczAPI_getDSValue() {
_logger.info("piczoAPI_getDSValue");
var msg = gAPI.mAPIToken + gAPI.mSession.token;
var msgArr = [];
for (var i = 0; i < msg.length; i++) {
msgArr.push(msg.charCodeAt(i));
}
this.cryptoHash.init(Components.interfaces.nsICryptoHash.MD5);
this.cryptoHash.update(msgArr, msgArr.length);
var sig = this.cryptoHash.finish(true);
var dsValue = escape(sig);
dsValue = dsValue.replace(/\+/g,"%2B");
dsValue = dsValue.replace(/\//g,"%2F");
dsValue = dsValue.replace(/\@/g,"%40");
return dsValue;
}
piczoAPI.prototype.convertBools =
function piczoAPI_convertBools(aParams) {
for (var p in aParams) {
if (!p.match(/^is/)) continue;
// I hope that this doesn't break anything
if (aParams[p]=="true") aParams[p] = "1";
if (aParams[p]=="false") aParams[p] = "0";
}
}
piczoAPI.prototype.convertTags =
function piczoAPI_convertTags(aParams) {
for (var p in aParams) {
if (p != "tags") continue;
var tags = aParams[p].split(",");
for (var i = 0; i < tags.length;++i) {
tags[i] = '"' + tags[i] + '"';
tags[i] = tags[i].replace(/\"+/g,'"');
}
aParams[p] = tags.join(",");
}
}
piczoAPI.prototype.isLoggedIn =
function piczoAPI_isLoggedIn()
{
return (this.mSession.token && this.mSession.token.length);
}
piczoAPI.prototype.handleDragDrop =
function piczoAPI_handleDragDrop(url, locX, locY) {
_logger.info("piczoAPI_handleDragDrop: " + url + ", " + locX + ", " + locY);
// http://server/go/placeimage
// parameters:
// imgid (Image Id)
// pageid (Destination page id)
// sl (x position)
// st (y position)
// Make sure we are logged in
// Hack it up
var imageID;
var results = Components.classes["@mozilla.org/hash-property-bag;1"]
.createInstance(Components.interfaces.nsIWritablePropertyBag2);
if (gSVC.webDetective.detectNoDOM("piczo", "piczoImageID", null, url, results)) {
imageID = results.getPropertyAsAString("imageID");
}
var currTab;
// Get active tab
var wm = Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator);
var win = wm.getMostRecentWindow('navigator:browser');
if (win) {
var gBrowser = win.gBrowser;
for(var i=0;i<gBrowser.mTabs.length;i++) {
var browser = gBrowser.mTabs[i].linkedBrowser;
if(browser.currentURI.spec == gBrowser.currentURI.spec) {
// We found the activce tab
currTab = browser;
}
}
}
// Get active tab's top-level document
_logger.debug("piczoAPI: document: " + currTab.contentDocument);
var theDoc = currTab.contentDocument;
// Make sure we're in a piczo edit page
results = Components.classes["@mozilla.org/hash-property-bag;1"]
.createInstance(Components.interfaces.nsIWritablePropertyBag2);
if (!gSVC.webDetective.detect("piczo", "piczoedit", theDoc, results)) {
// not a piczo edit page, return.
_logger.info("[piczoAPI] handleDragDrop() - Not a piczo edit page");
return false;
}
const PAGEID_STR = "pageid";
var serverLoc;
var loc = currTab.currentURI.spec;
if(loc.match(/:\/\/([^\/]*)\//)) {
serverLoc = RegExp.$1;
}
_logger.debug("piczoAPI: ServerLoc = " + serverLoc);
// Get array of top-level documents' immediate children documents (sub-frames)
var frames = theDoc.getElementsByTagName('frame');
var iframes = theDoc.getElementsByTagName('iframe');
// apply webdetective rule to each document and grab pageid
var frameFound = null;
var pageID = null;
results = Components.classes["@mozilla.org/hash-property-bag;1"]
.createInstance(Components.interfaces.nsIWritablePropertyBag2);
for (var i = 0; i < frames.length; i++) {
if (gSVC.webDetective.detect("piczo", "webedit", frames[i].contentDocument, results)) {
pageID = results.getPropertyAsAString(PAGEID_STR);
frameFound = frames[i];
break;
}
}
for (var i = 0; i < iframes.length && !frameFound; i++) {
if (gSVC.webDetective.detect("piczo", "webedit", iframes[i].contentDocument, results)) {
pageID = results.getPropertyAsAString(PAGEID_STR);
frameFound = iframes[i];
break;
}
}
_logger.debug("piczoAPI: pageid=" + pageID);
// Setup the url
var aURL = "http://" + serverLoc
+ "/go/placeimage?imgid=" + imageID
+ "&pageid=" + pageID
+ "&sl=" + locX
+ "&st=" + locY;
// Handler for response.
var listener = {
onSuccess: function (aSubject, aTopic) {
_logger.info("[piczoAPI].handleDragDrop() handleDragDropListener.onSuccess()");
_logger.debug("page frame before string mangling: " + frameFound.src);
// need to do a little string mangling to fool the service to reload a
// child frame instead of the parent page
// pass in the child frame pageid and reload
var re = /pageid=\d+/;
frameFound.src = frameFound.src.replace(re, PAGEID_STR + "=" + pageID);
_logger.debug("page frame after string mangling: " + frameFound.src);
return true;
},
onError: function (flockError) {
return false;
}
}
// Make simple xmlhttprequest to "move" the image to the right location
var hr = Components.classes['@mozilla.org/xmlextras/xmlhttprequest;1']
.createInstance(Components.interfaces.nsIXMLHttpRequest);
hr.QueryInterface(Components.interfaces.nsIJSXMLHttpRequest);
hr.onreadystatechange = function (aEvent) {
_logger.debug("[piczoAPI].call(): hr.onreadystatechange for Moving URL: "+hr.readyState);
if (listener) {
if (hr.readyState == 4) {
try {
if (hr.status/100 == 2) {
try {
listener.onSuccess(hr, aURL);
} catch (ex) {
_logger.debug(ex);
listener.onError(null);
}
} else {
// HTTP error
listener.onError(null);
}
} catch (ex) {
_logger.info(ex);
var err = {
errorCode: Components.interfaces.flockIError.PHOTOSERVICE_UNAVAILABLE,
errorString: "Request did not complete."
};
listener.onError(err);
}
}
}
};
hr.open("GET", aURL, true);
hr.send(null);
// We are returning true at this point because we made it to the send() call,
// but we won't know if the send actually succeeded because it is being called
// asynchronously (and cannot be called synchronously, as we need to use the
// callbacks).
return true;
}
piczoAPI.prototype.getFriends =
function piczoAPI_getFriends(aListener)
{
_logger.info("[piczoAPI].getFriends()");
var api = this;
var getNodeSubvalue = function (aNode) {
var longest = "";
for (var i = 0; i < aNode.childNodes.length; i++) {
var item = aNode.childNodes.item(i);
if (item.nodeValue.length > longest.length) {
longest = item.nodeValue;
}
}
return longest;
};
var friendsListener = {
onSuccess: function (aSubject, aTopic) {
_logger.info("[piczoAPI].getFriends() friendsListener.onSuccess()");
_logger.debug(aSubject.responseText);
var replyEl = aSubject.responseXML.getElementsByTagName("lookup.reply").item(0);
var friendsEl = replyEl.getElementsByTagName("friends").item(0);
var friendEls = friendsEl.getElementsByTagName("friend");
var friends = [];
for (var i = 0; i < friendEls.length; i++) {
var friendEl = friendEls.item(i);
var primaryProfEl = friendEl.getElementsByTagName("primary-profile").item(0);
var thumbEl = primaryProfEl.getElementsByTagName("thumbnail").item(0);
var websiteEl = primaryProfEl.getElementsByTagName("website-link").item(0);
friends.push({
id: friendEl.getAttribute("guid"),
name: getNodeSubvalue(friendEl.getElementsByTagName("name").item(0)),
avatarURL: getNodeSubvalue(thumbEl.getElementsByTagName("uri").item(0)),
URL: getNodeSubvalue(websiteEl.getElementsByTagName("uri").item(0))
});
}
aListener.onSuccess(friends, aTopic);
},
onError: function (aSubject, aTopic, aFlockError) {
_logger.info("[piczoAPI].getFriends() friendsListener.onError()");
if (api.handleStaleToken(aSubject)) {
// Resubmit the request with the new token
callGetFriends();
} else {
aListener.onError(aFlockError);
}
}
};
var callGetFriends = function () {
var url = gStrings["api-friends-URL"];
var headers = {
"ts": api.getTS(),
"sn": api.mSession.token,
};
api.call("get", url, headers, null, friendsListener, true);
};
callGetFriends();
}
// ========== END piczoAPI class ==========
// ==============================================
// ========== BEGIN piczoAccount class ==========
// ==============================================
function piczoAccount()
{
_logger.info("piczoAccount CONSTRUCTOR");
this.acUtils = Components.classes["@flock.com/account-utils;1"]
.getService(Components.interfaces.flockIAccountUtils);
this._coop = Components.classes["@flock.com/singleton;1"]
.getService(Components.interfaces.flockISingleton)
.getSingleton("chrome://flock/content/common/load-faves-coop.js")
.wrappedJSObject;
this.mAPI = gAPI;
this._ctk = {
interfaces: [
"nsISupports",
"flockIWebServiceAccount",
"flockIMediaWebServiceAccount",
"flockIMediaUploadAccount",
],
};
getCompTK().addAllInterfaces(this);
_logger.debug("piczoAccount Constructor End.");
}
piczoAccount.prototype.urn = null;
// BEGIN flockIWebServiceAccount interface
piczoAccount.prototype.login =
function piczoAccount_login(aListener)
{
var account = this;
var c_acct = account._coop.get(account.urn);
var loginListener = {
onSuccess: function (aSubject, aTopic) {
account.acUtils.ensureOnlyAuthenticatedAccount(account.urn);
c_acct.piczo_guid = account.mAPI.mSession.userGUID;
if (aListener) { aListener.onSuccess(aSubject, aTopic); }
},
onError: function (aSubject, aTopic, aError) {
c_acct.isAuthenticated = false;
if (aListener) { aListener.onError(aSubject, aTopic, aError); }
}
};
var pw = this.acUtils.getPassword("urn:piczo:service"+':'+c_acct.accountId);
this.mAPI.login(pw.user, pw.password, loginListener);
}
piczoAccount.prototype.logout =
function piczoAccount_logout(aListener)
{
_logger.info("{flockIWebServiceAccount}.logout()");
var c_acct = this._coop.get(this.urn);
if (c_acct.isAuthenticated) {
try {
this.mAPI.logout();
} catch (ex) {
_logger.warn("API logout call failed with error: "+ex);
}
Cc[CONTRACT_ID].getService(Ci.flockIWebService).logout();
c_acct.isAuthenticated = false;
}
}
piczoAccount.prototype.activate =
function piczoAccount_activate(aListener)
{
_logger.info("{flockIWebServiceAccount}.activate()");
var c_acct = this._coop.get(this.urn);
//c_acct.isTransient = false;
var account = this;
var loginListener = {
onSuccess: function (aSubject, aTopic) {
_logger.info(".activate() loginListener.onSuccess()");
// XXX TODO FIXME: API login
if (aListener) aListener.onSuccess(account, "accountAuthorized");
c_acct.isPollable = true;
account.acUtils.ensureOnlyAuthenticatedAccount(account.urn);
},
onError: function (aSubject, aTopic, aError) {
_logger.info(".activate() loginListener.onError()");
c_acct.isAuthenticated = true;
}
};
//this.acUtils.makeTempPasswordPermanent(this.service.urn+':'+c_acct.accountId);
this.login(loginListener);
// Assume login will succeed. Listener will handle failures.
c_acct.isAuthenticated = true;
}
// END flockIWebServiceAccount interface
// ========== END piczoAccount class ==========
// =========================================
// ========== BEGIN XPCOM Support ==========
// =========================================
function createModule(aParams) {
return {
registerSelf: function (aCompMgr, aFileSpec, aLocation, aType) {
aCompMgr.QueryInterface(Ci.nsIComponentRegistrar);
aCompMgr.registerFactoryLocation( aParams.CID, aParams.componentName,
aParams.contractID, aFileSpec,
aLocation, aType );
var catMgr = Cc["@mozilla.org/categorymanager;1"]
.getService(Ci.nsICategoryManager);
if (!aParams.categories) { aParams.categories = []; }
for (var i = 0; i < aParams.categories.length; i++) {
var cat = aParams.categories[i];
catMgr.addCategoryEntry( cat.category, cat.entry,
cat.value, true, true );
}
},
getClassObject: function (aCompMgr, aCID, aIID) {
if (!aCID.equals(aParams.CID)) { throw Cr.NS_ERROR_NO_INTERFACE; }
if (!aIID.equals(Ci.nsIFactory)) { throw Cr.NS_ERROR_NOT_IMPLEMENTED; }
return { // Factory
createInstance: function (aOuter, aIID) {
if (aOuter != null) { throw Cr.NS_ERROR_NO_AGGREGATION; }
var comp = new aParams.componentClass();
if (aParams.implementationFunc) { aParams.implementationFunc(comp); }
return comp.QueryInterface(aIID);
}
};
},
canUnload: function (aCompMgr) { return true; }
};
}
// NS Module entrypoint
function NSGetModule(aCompMgr, aFileSpec) {
return createModule({
componentClass: piczoService,
CID: CLASS_ID,
contractID: CONTRACT_ID,
componentName: CATEGORY_COMPONENT_NAME,
implementationFunc: function (aComp) { getCompTK().addAllInterfaces(aComp); aComp.init(); },
categories: [
{ category: "wsm-startup", entry: CATEGORY_COMPONENT_NAME, value: CONTRACT_ID },
{ category: "flockWebService", entry: CATEGORY_ENTRY_NAME, value: CONTRACT_ID },
{ category: "flockMediaProvider", entry: CATEGORY_ENTRY_NAME, value: CONTRACT_ID }
]
});
}
// ========== END XPCOM Support ==========